#include <linux/regmap.h>
#include <linux/sysfs.h>
#include "virt0701_driver.h"
#define DEV_NAME "virt0701_dev"
static struct regmap_config virt_regulator_regmap_config = {
	.reg_bits = 8,
	.val_bits = 16,
};
	


static struct regulator_consumer_supply virt_regulator_0701_volt_supplies[] = {
	REGULATOR_SUPPLY("virt-vcc", "virt_consumer01"),
};

/* VAUX3 for LCD board */
static struct regulator_init_data virt_regulator_0701_volt = {
	.constraints = {
		.min_uV			= 2800000,
		.max_uV			= 2800000,
		.apply_uV		= true,
		.valid_ops_mask		= REGULATOR_CHANGE_STATUS,
	},
	.num_consumer_supplies		= ARRAY_SIZE(virt_regulator_0701_volt_supplies),
	.consumer_supplies		= virt_regulator_0701_volt_supplies,
};

#define VIRT_VOLTAGE_SEL_REG		0x01
#define VIRT_VOLRTAGE_ENABLE_REG	0x02

/*
sysfs device attribute
*/

static void virt_regulator_dev_release(struct device *dev)
{

}


static virt_regulator_plat_data_t virt_regulator_data ={
	.init_data = &virt_regulator_0701_volt,
};
static struct platform_device virt_regulator_platform_device = {
	.name = "virt_regulator_dev",
	.id = -1,
	.dev = {
		.platform_data = &virt_regulator_data,
		.release = virt_regulator_dev_release
	}
};


static ssize_t virt_regulator_volt_sel_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	int reg_value = 0;
	virt_regulator_dev_t  *devp = dev_get_drvdata(dev);
	int ret = 0;

	if(devp == NULL || buf == NULL)
		return -EINVAL;


	ret = regmap_read(devp->regmap, VIRT_VOLTAGE_SEL_REG, &reg_value);
	if(ret == 0)
		return  sprintf(buf, "%d\n", reg_value);

	return ret;
}
static ssize_t virt_regulator_enable_show(struct device *dev, struct device_attribute *attr, char *buf)
{
	int reg_value = 0;
	virt_regulator_dev_t  *devp = dev_get_drvdata(dev);
	int ret = 0;

	if(devp == NULL || buf == NULL)
		return -EINVAL;


	ret = regmap_read(devp->regmap, VIRT_VOLRTAGE_ENABLE_REG, &reg_value);
	if(ret == 0)
		return  sprintf(buf, "%d\n", reg_value);

	return ret;
}


static DEVICE_ATTR(voltage_sel, S_IRUSR, virt_regulator_volt_sel_show, NULL);
static DEVICE_ATTR(voltage_enable, S_IRUSR, virt_regulator_enable_show, NULL);

static struct attribute *virt_regulator_attrs[] =
{
	&dev_attr_voltage_sel.attr,
	&dev_attr_voltage_enable.attr,
	NULL
};
	
static const struct attribute_group virt_regulator_attr_group = 
{
	.attrs = virt_regulator_attrs,
};

static int virt0701_regulator_probe(struct i2c_client *client, const struct i2c_device_id *id)
{
	int result = -ENODEV;
	virt_regulator_dev_t  *devp;
	printk("%s:%d\n", __FUNCTION__, __LINE__);

	if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C))
		return -EIO;

	devp = devm_kzalloc(&client->dev, sizeof(virt_regulator_dev_t),GFP_KERNEL);
	if(devp == NULL)
	{
		printk(KERN_ERR"%s:Init:malloc failed\n", __FUNCTION__);
		return -ENOSPC;
	}
	memcpy(devp->name, DEV_NAME, sizeof(DEV_NAME));

	devp->client = client;
	i2c_set_clientdata(client, devp);
	devp->regmap = devm_regmap_init_i2c(devp->client, &virt_regulator_regmap_config);
	if (IS_ERR(devp->regmap)) 
	{
		result = PTR_ERR(devp->regmap);
		return result;
	}

	result = sysfs_create_group(&(client->dev.kobj), &virt_regulator_attr_group);
	if(result != 0)
	{
		printk("%s:%d create device attributes failed\n", __FUNCTION__, __LINE__);
		return result;
	}

	virt_regulator_data.regmap = devp->regmap;
	printk("consumer num=%d\n", virt_regulator_data.init_data->num_consumer_supplies);
	result = platform_device_register(&virt_regulator_platform_device);

	return result;
}

static int virt0701_regulator_remove(struct i2c_client *client)
{
	sysfs_remove_group(&(client->dev.kobj), &virt_regulator_attr_group);
	platform_device_unregister(&virt_regulator_platform_device);
	return 0;
}

static const struct of_device_id virtual_regulator_of_match[] = {
	{
		.compatible = "virtual,virt_regulator0701",
	},
	{},
};

MODULE_DEVICE_TABLE(of, virtual_regulator_of_match);

static const struct i2c_device_id virt0701_regulator_dev_id[] = {
	{"virt_regulator0701", 0},
	{},
};

static struct i2c_driver virt0701_regulator_dev_driver = {
	.driver = {
		.name	= "virt0701_regulator_driver",
		.of_match_table = of_match_ptr(virtual_regulator_of_match),
	},
	.probe      = virt0701_regulator_probe,
	.remove     = virt0701_regulator_remove,
	.id_table   = virt0701_regulator_dev_id,
};

module_i2c_driver(virt0701_regulator_dev_driver);

MODULE_DESCRIPTION("Virtual I2c Regulator Device Drivers"); 
MODULE_LICENSE("GPL");
MODULE_AUTHOR("jerry_chg");
